package com.geovis.emergency.spd.biz.pc.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.geovis.common.auth.util.AuthUtil;
import com.geovis.common.core.constant.CommonConstants;
import com.geovis.emergency.spd.biz.basic.mapper.BasicDutyOrgMapper;
import com.geovis.emergency.spd.biz.basic.service.IBasicDutyPostService;
import com.geovis.emergency.spd.biz.pc.mapper.*;
import com.geovis.emergency.spd.biz.pc.service.IPcDrillDutyOrgService;
import com.geovis.emergency.spd.biz.pc.service.IPcDutyService;
import com.geovis.emergency.spd.biz.system.mapper.SystemFileMapper;
import com.geovis.emergency.spd.biz.system.mapper.SystemPostMapper;
import com.geovis.emergency.spd.biz.system.service.ISystemUserService;
import com.geovis.emergency.spd.biz.system.wrapper.ForestNodeMerger;
import com.geovis.emergency.spd.cache.UserCache;
import com.geovis.emergency.spd.entity.basic.entity.BasicDutyOrg;
import com.geovis.emergency.spd.entity.basic.entity.BasicDutyPost;
import com.geovis.emergency.spd.entity.mobile.pojo.vo.MobileDutyTree;
import com.geovis.emergency.spd.entity.pc.entity.*;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcDrillDutyOrganDTO;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcDrillDutyStatisticDTO;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcDutyDTO;
import com.geovis.emergency.spd.entity.pc.pojo.dto.PcDutyImtDTO;
import com.geovis.emergency.spd.entity.pc.pojo.enums.DutyUserType;
import com.geovis.emergency.spd.entity.pc.pojo.enums.RollCallStatusEnum;
import com.geovis.emergency.spd.entity.pc.pojo.enums.StatusEnum;
import com.geovis.emergency.spd.entity.pc.pojo.vo.PcDrillOrgCallUsersVo;
import com.geovis.emergency.spd.entity.pc.pojo.vo.PcDrillDutyOrgUserVO;
import com.geovis.emergency.spd.entity.pc.pojo.vo.PcDrillDutyOrgVO;
import com.geovis.emergency.spd.entity.pc.pojo.vo.TreeVO;
import com.geovis.emergency.spd.entity.system.entity.SystemFile;
import com.geovis.emergency.spd.entity.system.entity.SystemPost;
import com.geovis.emergency.spd.entity.system.entity.SystemUser;
import com.geovis.emergency.spd.excel.DutyExcel;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.collectingAndThen;
import static java.util.stream.Collectors.toCollection;

/**
 * <p>
 * 应急预案指挥模块-值班排班表 服务实现类
 * </p>
 *
 * @author 曾德实
 * @since 2022-04-30
 */

@Service
@RequiredArgsConstructor
@Slf4j
public class PcDutyServiceImpl extends ServiceImpl<PcDutyMapper, PcDuty> implements IPcDutyService {

    private final IBasicDutyPostService basicDutyPostService;

    private final ISystemUserService systemUserService;

    private final PcCheckInMapper pcCheckInMapper;

    private final SystemFileMapper systemFileMapper;

    private final SystemPostMapper systemPostMapper;

    private final BasicDutyOrgMapper basicDutyOrgMapper;
    ;

    private final PcRollCallPersonMapper pcRollCallPersonMapper;

    private final PcRollCallMapper pcRollCallMapper;

    private final PcDrillDutyUserMapper pcDrillDutyUserMapper;

    private final PcDrillDutyOrgMapper pcDrillDutyOrgMapper;

    private final IPcDrillDutyOrgService pcDrillDutyOrgService;
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void imt(PcDutyImtDTO imtDTO) {
        if (ObjectUtil.isEmpty(imtDTO)) {
            return;
        }
        Assert.notNull(imtDTO.getPcDrillId(), "演练id不能为空");
        Assert.notNull(imtDTO.getFileId(), "排班Excel文件id不能为空");

        SystemFile systemFile = systemFileMapper.selectById(imtDTO.getFileId());
        FileUtil.readBytes(systemFile.getDir() + systemFile.getPath());
        File file = new File(systemFile.getDir() + systemFile.getPath());
        Assert.notNull(file, "排班Excel文件不存在");
        List<DutyExcel> excelData = Lists.newArrayList();
        // 1、Excel解析数据
        EasyExcel.read(file, DutyExcel.class, new AnalysisEventListener<DutyExcel>() {
            @Override
            public void invoke(DutyExcel data, AnalysisContext context) {

                excelData.add(data);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {

            }
        }).autoTrim(true).sheet(0).headRowNumber(2).doRead();
        // 2、解析出要保存的全部数据
        List<PcDuty> pcDutyList = parseDutyExcelData(imtDTO.getPcDrillId(), excelData);
        Assert.notEmpty(pcDutyList, "Excel未解析到任何数据");

        saveBatch(pcDutyList);


    }

    @Override
    public List<PcDrillDutyOrgVO> getOrgCallTree(String pcDrillId) {
        //获取点名记录
        PcRollCall pcRollCall = pcRollCallMapper.selectOne(
                Wrappers.lambdaQuery(PcRollCall.class)
                        .eq(PcRollCall::getPcDrillId, pcDrillId)
                        .orderByDesc(PcRollCall::getCreateTime)
                        .last("limit 1")
        );
        List<PcRollCallPerson> pcRollCallPersonList = Lists.newArrayList();
        if (ObjectUtil.isNotNull(pcRollCall)) {

            pcRollCallPersonList = pcRollCallPersonMapper.selectList(
                    Wrappers.lambdaQuery(PcRollCallPerson.class)
                            .eq(PcRollCallPerson::getPcDrillId, pcDrillId)
                            .eq(PcRollCallPerson::getStatus, RollCallStatusEnum.CONFIRMED.getCode())
                            .eq(PcRollCallPerson::getPcRollCallId, pcRollCall.getId())
            );
        }
        //注意目前点名的情况好像是，都是将节点下的配置方案时的人员全部都纳入点名人员，所以这里是从这个接口那全部组织架构及人，// 如果是点名时，将部分人员纳入点名的范围，则要重新写逻辑

        List<PcDrillDutyOrgVO> drillDutyOrgList = pcDrillDutyOrgService.getDrillDutyOrg(pcDrillId, null,null);
        //先处理第一个根节点，再递归处理子节点
        PcDrillDutyOrgVO rootOrg=drillDutyOrgList.get(0);
        setUpStatData(rootOrg,pcRollCallPersonList);
        setUpChildCallStat(rootOrg.getChildren(),pcRollCallPersonList);
        return drillDutyOrgList;
    }

    /**
     * 统计本节点的签到情况
     */
    private void setUpStatData(PcDrillDutyOrgVO org,List<PcRollCallPerson> pcRollCallPersonList)
    {
        //该节点总人数
        Integer allUserCount=0;
        //签名总人数
        Integer callUserCount=0;

        if(!CollectionUtils.isEmpty(org.getDutyOrgDeptList()))
        {
            List<PcDrillOrgCallUsersVo> usersVos=getOrgCallUsersVos(org.getDutyOrgDeptList());
            allUserCount=usersVos.size();
            if(!CollectionUtils.isEmpty(pcRollCallPersonList))
            {
                //当前节点的签到人员列表
                List<PcRollCallPerson> orgCallPersons=pcRollCallPersonList.stream().filter(l->org.getId().equals(l.getBasicDutyPostId())).collect(Collectors.toList());
                if(!CollectionUtils.isEmpty(orgCallPersons))
                {
                    callUserCount=orgCallPersons.size();
                    List<String> callPersonIds=orgCallPersons.stream().map(PcRollCallPerson::getPersonId).collect(Collectors.toList());
                    callPersonIds.stream().forEach(callId->{
                        usersVos.stream().filter(usersVo->usersVo.getPrincipalId().equals(callId)).findFirst().ifPresent(u->u.setStatus("1"));
                    });

                }
            }
            org.setCallUsers(usersVos);

        }
        String callStat=StrUtil.format("{}/{}",callUserCount,allUserCount);
        org.setCallStat(callStat);

    }

    /**
     * 统计子节点的签到情况
     */
    private void setUpChildCallStat(List<PcDrillDutyOrgVO> orgVOS,List<PcRollCallPerson> pcRollCallPersonList)
    {

        for(PcDrillDutyOrgVO org:orgVOS)
        {
            //1.统计本节点情况
            setUpStatData(org,pcRollCallPersonList);
            //2.统计child节点情况
            if(!CollectionUtils.isEmpty(org.getChildren()))
            {
                setUpChildCallStat(org.getChildren(),pcRollCallPersonList);
            }
        }
    }

    /**
     * 将当前节点的所有人都映射成id和name
     * @param dutyOrgDeptList
     * @return
     */
    private List<PcDrillOrgCallUsersVo> getOrgCallUsersVos(List<PcDrillDutyOrgUserVO> dutyOrgDeptList)
    {

        List<PcDrillOrgCallUsersVo> usersVos=new ArrayList<>();
        for(PcDrillDutyOrgUserVO drillDutyOrgUserVO:dutyOrgDeptList)
        {
            String[] userIds=drillDutyOrgUserVO.getPrincipalIds().split(",");
            String[] userNames=drillDutyOrgUserVO.getPrincipalNames().split(",");
            String[] phones=null;
            if(StringUtils.hasText(drillDutyOrgUserVO.getPrincipalPhones()))
            {
                phones=drillDutyOrgUserVO.getPrincipalPhones().split(",");
            }
            for(int x=0;x<userIds.length;x++)
            {
                PcDrillOrgCallUsersVo usersVo=new PcDrillOrgCallUsersVo();
                usersVo.setPrincipalId(userIds[x]);
                usersVo.setPrincipalName(userNames[x]);
                if(null!=phones)
                {
                    //可能出现某个用户手机号不存在的情况，如a,,b
                    if(x<phones.length)
                    {
                        usersVo.setPrincipalPhone(phones[x]);
                    }
                }
                usersVo.setStatus("0");
                usersVos.add(usersVo);
            }
        }
        return usersVos;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void reImt(PcDutyImtDTO imtDTO) {
        //删除原有排班数据
        baseMapper.delete(
                Wrappers.<PcDuty>lambdaQuery()
                        .eq(PcDuty::getPcDrillId, imtDTO.getPcDrillId())
        );
        imt(imtDTO);
    }

    @Override
    public PcDutyDTO getByPersonId(String personId) {
        return baseMapper.selectByPersonId(personId);
    }

    @Override
    public List<PcDutyDTO> getByDrillId(String drillId) {
        return baseMapper.selectByDrillId(drillId);
    }

    @Override
    public List<PcDrillDutyStatisticDTO> getGroupByDrillId(String drillId) {
        // 查询演练组所有成员
        List<PcDutyDTO> dutyDTOList = baseMapper.selectByDrillId(drillId);
        if (CollUtil.isEmpty(dutyDTOList)) {
            return CollUtil.list(false);
        }
        // 查询签到的人数信息
        Map<String, PcCheckIn> checkInMap = IterUtil.toMap(pcCheckInMapper.selectList(Wrappers.lambdaQuery(PcCheckIn.class)
                .eq(PcCheckIn::getPcDrillId, drillId)), PcCheckIn::getPersonId);

        Map<String, List<PcDutyDTO>> dutyGroupMap = IterUtil.toListMap(dutyDTOList, PcDutyDTO::getGroupName);
        List<PcDrillDutyStatisticDTO> list = CollUtil.newArrayList();

        for (Map.Entry<String, List<PcDutyDTO>> entry : dutyGroupMap.entrySet()) {
            PcDrillDutyStatisticDTO dto = new PcDrillDutyStatisticDTO();
            dto.setGroupName(entry.getKey())
                    .setRealNum(0)
                    .setShouldNum(entry.getValue().size());
            List<PcDrillDutyStatisticDTO.DutyPersonDTO> detailList = CollUtil.list(false);
            entry.getValue().forEach(item -> {
                PcDrillDutyStatisticDTO.DutyPersonDTO dutyPersonDTO = new PcDrillDutyStatisticDTO.DutyPersonDTO(
                        item.getId(),
                        item.getPersonId(),
                        item.getPersonName(),
                        item.getBasicDutyPostName());
                dutyPersonDTO.setGroupId(item.getGroupId());
                dutyPersonDTO.setPostId(item.getPostId());
                if (checkInMap.containsKey(dutyPersonDTO.getPersonId())) {
                    dutyPersonDTO.setCheckIn(CommonConstants.YES);
                    dto.setRealNum(dto.getRealNum() + 1);
                }
                detailList.add(dutyPersonDTO);
            });
            dto.setDetailList(detailList);
            list.add(dto);
        }
        return list;
    }

    @Override
    public List<PcDrillDutyOrganDTO> getDutyOrganByDrillId(String drillId) {
        List<PcDrillDutyOrganDTO> result = CollUtil.newArrayList();
        // 查询演练组所有成员
        List<PcDuty> dutyDTOList = baseMapper.selectList(Wrappers.lambdaQuery(PcDuty.class).eq(PcDuty::getPcDrillId, drillId));
        if (CollUtil.isEmpty(dutyDTOList)) {
            return result;
        }
        dutyDTOList.forEach(item -> result.add(new PcDrillDutyOrganDTO(item)));
        // 查询值班机构
        List<BasicDutyPost> basicDutyPostList = basicDutyPostService.list();
        basicDutyPostList.forEach(item -> result.add(new PcDrillDutyOrganDTO(item)));
        return result;
    }


    /**
     * 解析出全部要保存的数据
     *
     * @param pcDrillId 演练id
     * @param excelData excel 数据
     * @return 返回要保存的全部数据
     */
    private List<PcDuty> parseAllSpdEventDuty(String pcDrillId, Map<Integer, Map<Integer, String>> excelData) {
        List<PcDuty> result = CollUtil.list(false);

        List<BasicDutyPost> basicDutyPostList = basicDutyPostService.list();

        if (ObjectUtil.isEmpty(basicDutyPostList) || ObjectUtil.isEmpty(excelData)) {
            return result;
        }

        // 用户表信息
        List<SystemUser> systemUserList = systemUserService.list();
        Map<String, SystemUser> systemUserMap = IterUtil.toMap(systemUserList, SystemUser::getRealName);

        // excel数据解析
        basicDutyPostList.forEach(basicDutyPost -> {
            Integer rowIndex = basicDutyPost.getExcelRowIndex();
            Integer cellIndex = basicDutyPost.getExcelCellIndex();

            Map<Integer, String> rowData = excelData.get(rowIndex);
            if (ObjectUtil.isEmpty(rowData)) {
                return;
            }
            String cellValue = rowData.get(cellIndex);
            if (ObjectUtil.isEmpty(cellValue)) {
                return;
            }
            // 单元格人员拆分
            String[] personArray = cellValue.split(",|，|、|;|；|/|\n");
            for (String person : personArray) {
                SystemUser systemUser = systemUserMap.get(person);
                Assert.notNull(systemUser, "【{}】在系统没有匹配到人员", person);
                result.add(new PcDuty().setPcDrillId(pcDrillId).setPostId(basicDutyPost.getId()).setPersonId(systemUser.getId()).setPersonName(systemUser.getRealName()));
            }

        });
        return result;
    }

    @Override
    @SneakyThrows
    public List<PcDuty> readDutyExcelData(String drillId, MultipartFile file) {
        List<DutyExcel> dutyExcelList = Lists.newArrayList();
        InputStream in = file.getInputStream();
        EasyExcel.read(in, DutyExcel.class, new AnalysisEventListener<DutyExcel>() {
            @Override
            public void invoke(DutyExcel dutyExcel, AnalysisContext analysisContext) {
                dutyExcelList.add(dutyExcel);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext analysisContext) {
                try {
                    in.close();
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }).autoTrim(true).headRowNumber(2).sheet(0).doRead();
        ;

        return parseDutyExcelData(drillId, dutyExcelList);
    }

    private List<PcDuty> parseDutyExcelData(String drillId, List<DutyExcel> dutyExcelList) {
        //组织架构
        List<BasicDutyOrg> orgList = basicDutyOrgMapper.selectList(Wrappers.lambdaQuery());
        //岗位表
        List<SystemPost> postList = systemPostMapper.selectList(Wrappers.lambdaQuery());
        List<PcDuty> list = Lists.newArrayList();
        //当前用户组
        String currentGroup = null;
        //当前用户组id
        String currentGroupId = null;

        //当前用单元
        String currentUnit = null;
        //当前单元id
        String currentUnitId = null;
        AtomicInteger index = new AtomicInteger(0);
        for (DutyExcel dutyExcel : dutyExcelList) {
            if (StrUtil.isNotBlank(dutyExcel.getGroupName())) {
                currentGroup = dutyExcel.getGroupName();
                String finalCurrentGroup1 = currentGroup;
                Optional<BasicDutyOrg> first = orgList.stream().filter(s -> finalCurrentGroup1.equals(s.getOrgName())).findFirst();
                if (first.isPresent()) {
                    currentGroupId = first.get().getId();
                }
            }
            if (StrUtil.isNotBlank(dutyExcel.getUnit())) {
                currentUnit = dutyExcel.getUnit();
                String finalCurrentUnit1 = currentUnit;
                Optional<BasicDutyOrg> first = orgList.stream().filter(s -> finalCurrentUnit1.equals(s.getOrgName())).findFirst();
                if (first.isPresent()) {
                    currentUnitId = first.get().getId();
                }
            }
            //用户组不为空
            if (StrUtil.isAllNotBlank(currentGroup, currentGroupId)) {
                String finalCurrentUnit = currentUnit;
                String finalCurrentUnitId = currentUnitId;
                String finalCurrentGroupId = currentGroupId;
                String finalCurrentGroup = currentGroup;
                if (StrUtil.isNotBlank(dutyExcel.getGroupLeader())) {
                    //领队列表
                    getUser(dutyExcel.getGroupLeader(), systemUser -> {
                        PcDuty pcDuty = new PcDuty()
                                .setPcDrillId(drillId)
                                .setGroupName(finalCurrentGroup)
                                .setGroupId(finalCurrentGroupId)
                                .setPersonName(systemUser.getRealName())
                                .setPersonId(systemUser.getId())
                                .setUserType(DutyUserType.GROUP_LEADER.getCode())
                                .setIdx(index.incrementAndGet());
                        //单元不为空，为指挥编组人员
                        if (StrUtil.isAllNotBlank(finalCurrentUnit, finalCurrentUnitId)) {
                            pcDuty.setIsGroup(StatusEnum.TRUE.getCode());
                        }

                        list.add(pcDuty);
                    });
                }
                //单元不为空
                if (StrUtil.isAllNotBlank(currentUnit, currentUnitId)) {
                    String unitLeader = dutyExcel.getUnitLeader();
                    if (StrUtil.isBlank(unitLeader)) {
                        unitLeader = dutyExcel.getUnitLeader2();
                    }
                    //单元负责人
                    if (StrUtil.isNotBlank(unitLeader)) {
                        getUser(unitLeader, systemUser -> {
                            PcDuty pcDuty = new PcDuty()
                                    .setPcDrillId(drillId)
                                    .setGroupName(finalCurrentGroup)
                                    .setGroupId(finalCurrentGroupId)
                                    .setUnitId(finalCurrentUnitId)
                                    .setUnitName(finalCurrentUnit)
                                    .setPersonName(systemUser.getRealName())
                                    .setPersonId(systemUser.getId())
                                    .setUserType(DutyUserType.UNIT_LEADER.getCode())
                                    .setIsGroup(StatusEnum.TRUE.getCode())
                                    .setIdx(index.incrementAndGet());
                            list.add(pcDuty);
                        });
                    }
                    if (StrUtil.isAllNotBlank(dutyExcel.getPostName(), dutyExcel.getUserName())) {
                        //岗位以及岗位人员不为空
                        Optional<SystemPost> first = postList.stream().filter(s -> dutyExcel.getPostName().equals(s.getName())).findFirst();
                        first.ifPresent(systemPost -> getUser(dutyExcel.getUserName(), systemUser -> {
                            PcDuty pcDuty = new PcDuty()
                                    .setPcDrillId(drillId)
                                    .setGroupName(finalCurrentGroup)
                                    .setGroupId(finalCurrentGroupId)
                                    .setUnitId(finalCurrentUnitId)
                                    .setUnitName(finalCurrentUnit)
                                    .setPostId(systemPost.getId())
                                    .setPostName(dutyExcel.getPostName())
                                    .setPersonName(systemUser.getRealName())
                                    .setPersonId(systemUser.getId())
                                    .setUserType(DutyUserType.ORDINARY_PEOPLE.getCode())
                                    .setIsGroup(StatusEnum.TRUE.getCode())
                                    .setIdx(index.incrementAndGet());
                            list.add(pcDuty);
                        }));
                    }
                }
            }
            //用户存在分组，但是用户不在系统机构表内的,非指挥编组的
            if (StrUtil.isNotBlank(currentGroup) && StrUtil.isBlank(currentGroupId) && StrUtil.isBlank(currentUnitId)) {
                if (StrUtil.isNotBlank(dutyExcel.getGroupLeader())) {
                    String finalCurrentGroup2 = currentGroup;
                    //组负责人
                    getUser(dutyExcel.getGroupLeader(), systemUser -> {
                        PcDuty pcDuty = new PcDuty()
                                .setPcDrillId(drillId)
                                .setGroupName(finalCurrentGroup2)
                                .setPersonName(systemUser.getRealName())
                                .setPersonId(systemUser.getId())
                                .setUserType(DutyUserType.GROUP_LEADER.getCode())
                                .setIsGroup(StatusEnum.FALSE.getCode())
                                .setIdx(index.incrementAndGet());
                        list.add(pcDuty);
                    });
                    //岗位
                    if (StrUtil.isAllNotBlank(dutyExcel.getPostName(), dutyExcel.getUserName())) {
                        getUser(dutyExcel.getUserName(), systemUser -> {
                            Optional<SystemPost> first = postList.stream().filter(s -> dutyExcel.getPostName().equals(s.getName())).findFirst();
                            PcDuty pcDuty = new PcDuty()
                                    .setPcDrillId(drillId)
                                    .setGroupName(finalCurrentGroup2)
                                    .setPostName(dutyExcel.getPostName())
                                    .setPersonName(systemUser.getRealName())
                                    .setPersonId(systemUser.getId())
                                    .setUserType(DutyUserType.ORDINARY_PEOPLE.getCode())
                                    .setIsGroup(StatusEnum.FALSE.getCode())
                                    .setIdx(index.incrementAndGet());
                            first.ifPresent(systemPost -> pcDuty.setPostId(systemPost.getId()));
                            list.add(pcDuty);
                        });
                    }
                }
            }
        }
        return list;
    }

    /**
     * 获取用户
     *
     * @param userName 用户名
     * @param func     回调
     */
    public void getUser(String userName, Consumer<SystemUser> func) {
        String[] userList = userName.split(",|，|、|;|；|/|\n");
        //多个单元负责任人
        Set<String> userListSet = CollUtil.set(false);
        userListSet.addAll(Arrays.asList(userList));
        for (String user : userListSet) {
            //TODO 如果后面有多个行政区域，查询用户需要按部门去过滤，根据名称查询可能存在重复情况
            SystemUser systemUser = UserCache.getUserByName(user);
            if (ObjectUtil.isNotNull(systemUser)) {
                func.accept(systemUser);
            }
        }
    }

    @Override
    public List<TreeVO> dutyTree(String drillId, List<String> groupList,boolean emptyUser) {
        LambdaQueryWrapper<PcDrillDutyUser> userWrapper = new LambdaQueryWrapper<>();
        userWrapper.eq(StrUtil.isNotBlank(drillId), PcDrillDutyUser::getPcDrillId, drillId);
        userWrapper.isNotNull(emptyUser,PcDrillDutyUser::getPrincipalIds);
        userWrapper.in(CollUtil.isNotEmpty(groupList), PcDrillDutyUser::getPcDrillOrgId, groupList);
        List<PcDrillDutyUser> pcDrillDutyUsers = pcDrillDutyUserMapper.selectList(userWrapper);

        LambdaQueryWrapper<PcDrillDutyOrg> orgWrapper = new LambdaQueryWrapper<>();
        orgWrapper.eq(StrUtil.isNotBlank(drillId), PcDrillDutyOrg::getPcDrillId, drillId);
        orgWrapper.in(CollUtil.isNotEmpty(groupList), PcDrillDutyOrg::getId, groupList);
        orgWrapper.orderByDesc(PcDrillDutyOrg::getParentId);
        orgWrapper.orderByAsc(PcDrillDutyOrg::getIdx);
        List<PcDrillDutyOrg> pcDrillDutyOrgs = pcDrillDutyOrgMapper.selectList(orgWrapper);
        List<TreeVO> userTreeVO = Lists.newArrayList();
        for (PcDrillDutyUser pcDrillDutyUser : pcDrillDutyUsers) {
            List<String> principalIdList = StrUtil.split(pcDrillDutyUser.getPrincipalIds(), ",");
            List<String> principalNameList = StrUtil.split(pcDrillDutyUser.getPrincipalNames(), ",");
            for (int i = 0; i < principalIdList.size(); i++) {
                TreeVO treeVO = new TreeVO();
                treeVO.setId(pcDrillDutyUser.getId()+i);
                treeVO.setParentId(pcDrillDutyUser.getPcDrillOrgId());
                treeVO.setName(principalNameList.get(i));
                treeVO.setExtra("user");
                treeVO.setExtra2(principalIdList.get(i));
                Optional<PcDrillDutyOrg> first = pcDrillDutyOrgs.stream().filter(s -> s.getId().equals(pcDrillDutyUser.getPcDrillOrgId())).findFirst();
                if (first.isPresent()) {
                    List<String> split = StrUtil.split(first.get().getAncestors(), ",");
                    if (split.size() > 1){
                        treeVO.setExtra1(split.get(1));
                    }else {
                        treeVO.setExtra1(first.get().getId());
                    }
                }
                userTreeVO.add(treeVO);
            }
        }

        List<TreeVO> orgTreeVO = pcDrillDutyOrgs.stream().map(e->{
            TreeVO treeVO = new TreeVO();
            treeVO.setId(e.getId());
            treeVO.setParentId(e.getParentId());
            treeVO.setName(e.getOrgName());
            return treeVO;
        }).collect(Collectors.toList());

        orgTreeVO.addAll(userTreeVO);
        List<TreeVO> treeList = ForestNodeMerger.merge(orgTreeVO);
        fixTreeVo(treeList);
        return treeList;
    }

    private void fixTreeVo(List<TreeVO> list){
        for (TreeVO treeVO : list) {
            if (CollUtil.isNotEmpty(treeVO.getChildren())){
                fixTreeVo(treeVO.getChildren());
            }else {
                if (ObjectUtil.isNotNull(treeVO.getExtra2())){
                    treeVO.setId(treeVO.getExtra2().toString());
                    SystemUser systemUser = UserCache.getUserById(treeVO.getExtra2().toString());
                    if (ObjectUtil.isNotNull(systemUser)) {
                        treeVO.setExtra2(systemUser.getUserName());
                    }else {
                        treeVO.setExtra2(null);
                    }
                }
            }
        }
    }

    @Override
    public List<MobileDutyTree> getDutyUser(String drillId, String parentId) {
        List<MobileDutyTree> result = new ArrayList<>();
        parentId = StrUtil.isBlank(parentId) ? StatusEnum.FALSE.getCode() : parentId;
        List<MobileDutyTree> mobileDutyTrees = basicDutyOrgMapper.getByDutyByParentId(parentId);
        if (!StatusEnum.FALSE.getCode().equals(parentId)) {
            List<MobileDutyTree> userList = baseMapper.getDutyUser(drillId, parentId);
            result.addAll(userList);
        }
        result.addAll(mobileDutyTrees);
        return result;
    }

    @Override
    public List<PcDuty> myGroupList(String drillId) {
        return baseMapper.selectList(
                Wrappers.lambdaQuery(PcDuty.class)
                        .eq(PcDuty::getPcDrillId, drillId)
                        .eq(PcDuty::getPersonId, AuthUtil.getCurrentUserId())
        ).stream().collect(
                collectingAndThen(
                        toCollection(() -> new TreeSet<>(comparing(PcDuty::getGroupId))), ArrayList::new
                )
        );
    }
}
